/**
 * Created by chester on 2016/5/29.
 */
package com.invexer.service.common {
import com.invexer.service.util.CursorUtil;

import flash.net.URLLoaderDataFormat;
import flash.net.URLRequestMethod;

import mx.rpc.events.FaultEvent;
import mx.rpc.events.InvokeEvent;
import mx.rpc.events.ResultEvent;
import mx.rpc.http.HTTPService;

import org.as3commons.logging.ILogger;

import org.as3commons.logging.LoggerFactory;


public class InvexerHttpService {
    private static var logger:ILogger = LoggerFactory.getClassLogger(InvexerHttpService);

    private var _httpServices:Array = new Array();

    public function sendGetRequest(api:String, params:Object, successCallback:Function, failCallback:Function, useBusyCursor:Boolean=false):void{
        sendRequest(RequestInfo.getNewRequestInfo(URLRequestMethod.GET, api, params, successCallback, failCallback, useBusyCursor));
    }

    public function sendPostRequest(api:String, params:Object, successCallback:Function, failCallback:Function, useBusyCursor:Boolean=false):void{
        sendRequest(RequestInfo.getNewRequestInfo(URLRequestMethod.POST, api, params, successCallback, failCallback, useBusyCursor));
    }


    public function sendPutRequest(api:String, params:Object, successCallback:Function, failCallback:Function, useBusyCursor:Boolean=false):void{
        sendRequest(RequestInfo.getNewRequestInfo(URLRequestMethod.PUT, api, params, successCallback, failCallback, useBusyCursor));
    }


    public function sendDeleteRequest(api:String, params:Object, successCallback:Function, failCallback:Function, useBusyCursor:Boolean=false):void{
        sendRequest(RequestInfo.getNewRequestInfo(URLRequestMethod.DELETE, api, params, successCallback, failCallback, useBusyCursor));
    }

    private function sendRequest(requestInfo:RequestInfo):void{
        requestInfo.onInvoke = function (event:InvokeEvent):void{
            httpsServiceOnInvoke(requestInfo, event);
        };
        requestInfo.onResult = function (event:ResultEvent):void{
            if(requestInfo.useBusyCursor) CursorUtil.removeBusyCursor();
            httpServiceOnResult(requestInfo, event);
        };
        requestInfo.onFault = function (event:FaultEvent):void{
            if(requestInfo.useBusyCursor) CursorUtil.removeBusyCursor();
            httpServiceOnFault(requestInfo, event);
        };

        var httpService:HTTPService =  _httpServices.length>0 ? _httpServices.pop() : new HTTPService();
        httpService.resultFormat = URLLoaderDataFormat.TEXT;;
        httpService.useProxy = false;
        httpService.url = requestInfo.api;
        httpService.method = requestInfo.requestType;
        httpService.addEventListener(InvokeEvent.INVOKE, requestInfo.onInvoke);
        httpService.addEventListener(ResultEvent.RESULT, requestInfo.onResult);
        httpService.addEventListener(FaultEvent.FAULT, requestInfo.onFault);

        if(requestInfo.useBusyCursor) CursorUtil.showBusyCursor();
        httpService.send(requestInfo.params);
    }

    private function httpsServiceOnInvoke(requestInfo:RequestInfo, event:InvokeEvent):void{
        logger.info(requestInfo.requestType + " " + requestInfo.api);
        logger.info("params: " + JSON.stringify(requestInfo.params));
    }

    private function httpServiceOnResult(requestInfo:RequestInfo, event:ResultEvent):void{
        requestInfo.successCallback(event.result);
        recycleHttpService(requestInfo);
    }

    private function httpServiceOnFault(requestInfo:RequestInfo, event:FaultEvent):void{
        requestInfo.failCallback(event);
        recycleHttpService(requestInfo);
    }

    private function recycleHttpService(requestInfo:RequestInfo):void{
        var httpService:HTTPService =  _httpServices.length>0 ? _httpServices.shift() : new HTTPService();
        httpService.resultFormat = null;
        httpService.url = null;
        httpService.method = null;
        httpService.removeEventListener(InvokeEvent.INVOKE, requestInfo.onInvoke);
        httpService.removeEventListener(ResultEvent.RESULT, requestInfo.onResult);
        httpService.removeEventListener(FaultEvent.FAULT, requestInfo.onFault);

        _httpServices.push(httpService);

        RequestInfo.recycleRequestInfo(requestInfo);
    }
}
}

class RequestInfo {
    private static var requestInfos:Array = new Array();

    public var useBusyCursor:Boolean;
    public var requestType:String;
    public var api:String;
    public var params:Object;
    public var successCallback:Function;
    public var failCallback:Function;

    public var onInvoke:Function;
    public var onResult:Function;
    public var onFault:Function;

    public static function  getNewRequestInfo(requestType:String, api:String, params:Object, successCallback:Function, failCallback:Function, useBusyCursor:Boolean=false):RequestInfo {
        var requestInfo:RequestInfo = requestInfos.length>0 ? requestInfos.shift() : new RequestInfo();
        requestInfo.useBusyCursor = useBusyCursor;
        requestInfo.requestType = requestType;
        requestInfo.api = api;
        requestInfo.params = params;
        requestInfo.successCallback = successCallback;
        requestInfo.failCallback = failCallback;

        return requestInfo;
    }

    public static function  recycleRequestInfo(requestInfo:RequestInfo):void {
        requestInfo.useBusyCursor = false;
        requestInfo.requestType = null;
        requestInfo.api = null;
        requestInfo.params = null;
        requestInfo.successCallback = null;
        requestInfo.failCallback = null;

        requestInfo.onInvoke = null;
        requestInfo.onResult = null;
        requestInfo.onFault = null;

        requestInfos.push(requestInfo);
    }
}
